<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
</head>
<body>
<p>下面是<a href="https://class.coursera.org/ml-004/class">机器学习公开课</a>每周的一些笔记。 公开课笔记的内容及练习题我已经放到<a href="https://git.oschina.net/JiaxiangZheng/Online-Course-Notes">我的GIT-OS</a>上了。</p>
<hr />
<h3 id="第一周-单变量线性回归问题">第一周 单变量线性回归问题</h3>
<p>本周内容主要是单变量的线性回归问题，对于这类问题，给定待拟合函数为<span class="math">\(h_\theta{}(x)=\theta_0+\theta_1x\)</span>，其损失函数可以定义为： <span class="math">\[J(\theta_0, \theta_1)=\frac{1}{2m}\sum_{i=1}^m(h_\theta(x^i)-y^i)^2\]</span> 给定训练的数据，要求出合理的参数得到合理的线性函数，即相当于最小化<span class="math">\(J(\theta)\)</span>了，注意到不同的<span class="math">\(\theta\)</span>决定了不同的拟合函数，从而也就得到不同的损失函数值。请<strong>注意</strong>：损失函数是关于参数的一维线性函数，而拟合函数则是关于<span class="math">\(x\)</span>的函数，可以不是线性的，但它假定参数已经知道了。</p>
<p>如何最小化损失函数，使得拟合的结果最接近真实结果呢？</p>
<p>梯度下降法表示为沿着初始点下降速度最快的方向进行移动，重新算出一个新的估计值，去迭代计算参数，即： <span class="math">\[\theta_j := \theta_j-\alpha\frac{\partial J(\theta)}{\partial{}\theta_j}\]</span> 其中，<span class="math">\(\alpha\)</span>为学习速率，它控制了每次迭代估计值的速率，注意，如果<span class="math">\(\alpha\)</span>太大，可能会导致整个过程发散，而如果太小，会导致收敛速度过慢。 <strong>此外</strong>，如果损失函数是一个非线性的问题（非凸），有可能初始值选择不当会导致收敛到局部最小值；而如果是凸函数，则是可以在数学证明上保证它得到全局最小值。但在这里，显然定义的代价函数是一个凸的。</p>
<p>对于上面的线性损失函数，事实上是不需要使用迭代的方法来计算最小值的，直接使用<strong>最小二乘法（Normal Equation）</strong>即可计算出全局最小值。</p>
<hr />
<h3 id="第二周-多变量线性回归问题">第二周 多变量线性回归问题</h3>
<p>这周内容主要是关于多变量的线性回归问题，包括使用梯度下降方法求解和最小二乘法求解。此外，再额外地加了一些octave的教程。</p>
<p>为方便后面的叙述，令<span class="math">\(x_j^{(i)}\)</span>表示第<span class="math">\(i\)</span>个样本的第<span class="math">\(j\)</span>个特征，所有的样本构成一个<span class="math">\(X\)</span>。<span class="math">\(x^i\)</span>表示第<span class="math">\(i\)</span>个训练样本，是一个向量。</p>
<p>前一周中拟合函数表示为<span class="math">\(h_\theta{}(x)=\theta_0+\theta_1x\)</span>，但现在变量有多个，方便地用向量形式表示即：<span class="math">\(h_\theta{}(x)=\theta^Tx\)</span>（这里<span class="math">\(x\)</span>实际上相当于增加了一维，第一维为1），可以将损失函数表示成： <span class="math">\[J(\theta)=\frac{1}{2m}\sum_{i=1}^m(h_\theta(x^i)-y^i)^2\]</span> 即表示为： <span class="math">\[J(\theta)=\frac{1}{2m}\sum_{i=1}^m(\theta^Tx^i-y^i)^2\]</span> 这时候，<span class="math">\(x^i_0\)</span>为1，使用梯度下降法则变为了： <span class="math">\[\theta_j := \theta_j-\alpha\frac{\partial J(\theta)}{\partial{}\theta_j} := \theta_j-\alpha\frac{1}{m}\sum_{i=1}^m(\theta^Tx^i-y^i)x_j^i\]</span></p>
<p><strong>特征归一化</strong>：通常情况下，不同的特征单位是不一样的，这意味着它们的数值相差可能在多个数量级之上，因此需要对不同特征的数值进行归一化（想象contour图变得又长又窄，梯度下降的速度就会非常地慢）。可以将所有的元素归一化到<span class="math">\([-1, 1]\)</span>，另一种方式是称为<code>Mean Normalization</code>的方法，它保证元素归一化到<span class="math">\([-0.5, 0.5]\)</span>，即： <span class="math">\[x=\frac{x-\mu}{S}\]</span> 其中<span class="math">\(\mu\)</span>表示平均值，<span class="math">\(S\)</span>表示元素的方差。</p>
<p><strong>学习速率<span class="math">\(\alpha\)</span>的优化</strong>：可以把损失函数随迭代次数而变化的曲线可视化出来，理论上曲线应该是不断地递减的。前面也提到，如果<span class="math">\(\alpha\)</span>太大，可能会发散，而对于足够小的 <span class="math">\(\alpha\)</span>，可以保证总是递减的，但这个时候收敛速度就很慢了。因此在选择参数的时候，可以先选择足够小的<span class="math">\(\alpha\)</span>，然后不断地调整到一个足够合理的参数。</p>
<p><strong>多项式回归</strong>：不仅仅可以对特征进行线性的组合，我们还可以将不同特征进行多项式组合，然后再线性拟合这个新的特征，有时候可以得到令人意想不到的效果。例如：我们原本是有<span class="math">\(x={x_1, x_2}\)</span>两个特征，按前面的线性回归方式，即<span class="math">\(h=\theta^Tx\)</span>，但我们可以组合出一个特征 <span class="math">\(x_3=x_1\times{}x_2\)</span>，然后转变成单变量(<span class="math">\(x_3\)</span>)的线性回归问题。</p>
<p><strong>最小二乘法</strong>：最小二乘法从理论上给出了线性回归问题的数学解析答案，即全局最小值的解。由于对于线性回归问题，其损失函数表示为二次函数<span class="math">\(J(\theta)\)</span>，使用微积分的知识，我们知道全局最小值对应的导数应该是0，即 <span class="math">\(\frac{\partial{}J(\theta)}{\partial\theta}=0\)</span>，从而可以求出<span class="math">\(\theta\)</span>的解析解。</p>
<p>推导过程：假设<span class="math">\(X\)</span>表示为所有数据构成的矩阵，其中第一列为全1，对应于<span class="math">\(\theta_0\)</span>的系数，对于每一行剩余列，即为每一个样本，于是<span class="math">\(X\)</span>即一个<span class="math">\(m\times{}(n+1)\)</span>的矩阵，而<span class="math">\(Y\)</span>表示<span class="math">\(m\times{}1\)</span>的向量，则<span class="math">\(J(\theta)=\frac{1}{2m}(X\theta-Y)^T(X\theta-Y)\)</span>，于是对<span class="math">\(\theta\)</span>求导则可以计算出： <span class="math">\[\theta=(X^TX)^{-1}X^TY\]</span> 在<strong>MATLAB</strong>中，这可以通过 <code>pinv(X'*X)*X'*Y</code>直接计算求解（注意，这里<span class="math">\((X^TX)^{-1}X^T\)</span>即矩阵的广义逆）。</p>
<p>两种方法比较：显然，梯度下降需要选择学习速度参数<span class="math">\(\alpha\)</span>，且需要大量的迭代过程；而对于最小二乘方法，无需任何参数的设置。但是，梯度下降对于非常大的数据量依然非常有效，但最小二乘法对于大数据量的情况下，就会导致矩阵异常庞大，从而可能造成计算资源的不足（计算逆矩阵非常地耗时，需要<span class="math">\(O(n^3)\)</span>）。</p>
<p>此外，如果<span class="math">\(m&lt;n\)</span>，即意味着特征数多于训练样本数，这个时候只能通过放弃一些不重要的特征，或者使用正则化的方法。</p>
<hr />
<h3 id="第三周-逻辑回归与正则化">第三周 逻辑回归与正则化</h3>
<h4 id="逻辑回归问题">逻辑回归问题</h4>
<p>首先，明白分类问题是指什么。从最简单的二分类问题开始，对于邮件的分类可以分为垃圾 邮件与非垃圾邮件，于是两个类别对应的值可以用0和1进行标识，具体0是指哪一个是无所 谓的。</p>
<p>这个时候，如果单纯地使用线性回归，得到一条直线区分两个类别，需要我们指定一个阈值 ，大于这个阈值就取1，否则就取0。这样做的坏处在于首先阈值的选择会很麻烦，另外如果 有一个非常大的噪声，会导致结果偏离非常地大。</p>
<p>这样就引入逻辑回归（Logistic Regression）这个概念了，注意，它与普通的回归问题不 同，主要是为了解决 0-1 的分类问题而引入的。假定我们的待拟合函数为<span class="math">\(h_\theta(x)\)</span>， 那么之前提到的线性回归问题为<span class="math">\(h_\theta(x)=\theta^Tx\)</span>，现在需要对这个函数作一点更 改，即变为： <span class="math">\[h_\theta(x)=g(\theta^Tx)\]</span> ，其中<span class="math">\(g(z)\)</span>为<code>sigmoid</code>函数 <span class="math">\(\frac{1}{1+e^{-z}}\)</span>。</p>
<p>这里突然引入的<code>sigmoid</code>函数用途何在呢？它保证输出的结果是落在0~1之间，我们可以解 释为结果为0的概率为<span class="math">\(h_\theta(x)\)</span>，为1的概率为<span class="math">\(1-h_\theta(x)\)</span>。即 <span class="math">\[h_\theta(x)=P(y=1|x;\theta)\]</span></p>
<p><strong>Decision Boundary</strong>：事实上，要保证输出的类别为1，即使得输出的概率大于 0.5，反应在<code>sigmoid</code>函数上，即<span class="math">\(z\geq0\)</span>，即<span class="math">\(\theta^Tx\geq0\)</span>，这样实际上反应到函数 图像上就相当于一个平面<span class="math">\(\theta^Tx=0\)</span>将数据分为两边，即对应的两个类。这个平面也称 为决策平面。</p>
<p>注意，前面提到的这个分界面是一个线性平面方程，如果我们的数据本身是需要用一个非线 性分界面分开呢，比如对应不同半径的圆？这个时候实际上我们的分界面应该是形如 <span class="math">\(\|x\|^2=C\)</span>这样的形式。这个时候需要用到前面提到的多项式回归，将已知的特征进行二 阶或更高阶的组合形成新的特征，从而可以解决这个非线性的问题（显然越复杂，它所组合 出来的非线性能力越强，但模型本身越复杂的话，也不见得是好事）。</p>
<p>现在我们考虑逻辑回归问题对应的损失函数：对于逻辑回归问题，如果我们继续使用与线性 回归类似的损失函数，那么定义出来的损失函数将是一个非凸函数（因为<span class="math">\(h_\theta(x)\)</span>具 有非凸性），这意味着我们将来使用梯度下降的时候不一定能够得到全局最小值。一个比较 合理的损失函数定义如下： <span class="math">\[J(\theta) = -\frac{1}{m}\sum_{i=1}^m(y^{(i)}\log{}h_\theta(x^{(i)}) + (1-y^{(i)})\log{}(1-h_\theta(x^{(i)})))\]</span></p>
<p>其意义在于，如果真实的<span class="math">\(y^i\)</span>为0，而预测的值为1，那么其概率应该接近0；反之如果预测 值为0，则概率为1，这样对应损失函数分别为无穷大和0。对于<span class="math">\(y^i=1\)</span>同理。对应的两种情 况图像分别如下图：</p>
<p><img src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/logistic-regression-cost-fuction-3.jpg" alt="regression-cost-function" width="400" /></p>
<p><img src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/logistic-regression-cost-fuction-4.jpg" alt="regression-cost-function" width="400" /></p>
<p>通过定义了损失函数，我们接下来就可以通过使用梯度下降的方法来最小损失函数求出回归 参数了。主要思路还是和前面一样，只不过这里的偏导数我们需要用新定义的重新计算： <span class="math">\[\begin{align}
    \frac{\partial{J(\theta)}}{\theta_j} 
    &amp; = - \frac{1}{m}\sum_{i=1}^m(\frac{y^i}{h_\theta({x^i})}\cdot{}\frac{\partial{h_\theta({x^i})}}{\partial{\theta_j}}
                                                                     - \frac{1-y^i}{1-h_\theta({x^i})}\cdot{}\frac{\partial{h_\theta({x^i})}}{\partial{\theta_j}}) \\
    &amp; = - \frac{1}{m}\sum_{i=1}^m\frac{\partial{h_\theta({x^i})}}{\partial{\theta_j}}(\frac{y^i-h_\theta({x^i})}{h_\theta({x^i})(1-h_\theta({x^i}))})
\end{align}\]</span></p>
<p>注意到<span class="math">\(h_\theta({x^i})\)</span>的定义（<code>sigmoid</code>函数），可以将它展开为对<span class="math">\(\theta\)</span>求导： <span class="math">\[\frac{\partial{h_\theta({x^i})}}{\partial{\theta_j}} = \frac{\partial{g(z)}}{\partial{z}}\cdot{}\frac{\partial{z}}{\partial{\theta_j}} =\frac{\partial{g(z)}}{\partial{z}}x_j^i\]</span> 其中<span class="math">\(g(z)\)</span>定义为<code>sigmoid</code>函数。<span class="math">\(\frac{\partial{g(z)}}{\partial{z}}=\frac{e^{-z}}{(1+e^{-z})^2}\)</span>，于是上面的偏导数即可变为：</p>
<p><span class="math">\[\begin{align}
    \frac{\partial{J(\theta)}}{\theta_j} &amp; = - \frac{1}{m}\sum_{i=1}^m{x_j^i}(y^i-h_\theta(x^i))\frac{\partial{g(z)}}{\partial{z}}\cdot{}\frac{1}{h_\theta({x^i})(1-h_\theta({x^i}))} \\
    &amp; = \frac{1}{m}\sum_{i=1}^m{x_j^i}(h_\theta(x^i)-y^i)
\end{align}\]</span></p>
<p>有木有发现它和之前推导的线性回归情况下的偏导在形式上是类似的呢？:)</p>
<p><strong>优化算法</strong>：</p>
<ul>
<li>梯度下降法（Gradient Descent）</li>
<li>共轭梯度法（Conjugate gradient）</li>
<li>BFGS</li>
<li>L-BFGS</li>
</ul>
<p>下面代码表示了如何使用<code>matlab</code>进行优化求解这些问题：</p>
<pre><code>%% 使用如下方法解方程
options = optimset(&#39;GradObj&#39;, &#39;on&#39;, &#39;MaxIter&#39;, &#39;100&#39;)
[optResult, functionVal, exitFlag] = fminunc(@costFunc, initialGuess, options)

function [jVal, gradient] = costFunc(theta)
    jVal = []
    gradient(1) = ...   % gradient zero 对第0个参数求偏导的值 
    ...
    gradient(n+1) = ...  % gradient n  对第n个参数求偏导的值 </code></pre>
<h4 id="正则化问题">正则化问题</h4>
<p>模型的估计过程中，经常会出现过拟合或欠拟合的情况。对于过拟合（overfitting）的情 况，我们应该如何避免呢？主要是有如下的方式：</p>
<ul>
<li>减小特征数
<ul>
<li>手工保留一些更有效的特征</li>
<li>模型选择</li>
</ul></li>
<li>正则化
<ul>
<li>保留特征，但可以利用<span class="math">\(\theta\)</span>之间的光滑性等作正则化</li>
</ul></li>
</ul>
<p>一方面，如果模型考虑的是比较复杂的特征高阶组合，我们可以得到比较准确的结果可以避 免欠拟合，但另一方面可能会导致对于训练数据，拟合出来的模型可以完美地穿过所有的训 练点，但整个模型反而是一个波动非常大的结果，这样就会有一个坏处，即模型不稳定。为 了避免这种情况，引入了正则化的方法，即在之前提到的代价函数的基础上，再加一个正则 项约束参数的一些特性。如通常我们会要求参数满足<span class="math">\(\sum_{i=1}^n\theta_i^2=0\)</span>，注意这 里不需要把<span class="math">\(\theta_0\)</span>加入正则项。</p>
<p>对于线性回归，加了一个<span class="math">\(L_2\)</span>正则项以后，梯度下降的过程中对参数的偏导我们就需要稍 作变化了，而对于使用最小二乘的方法，就可以调整矩阵重新运算了：（注意这里<span class="math">\(\theta\)</span> 的下标是从0开始，但式中后面部分是从<span class="math">\(\theta_1\)</span>开始进行正则化） <span class="math">\[J(\theta)=\frac{1}{2m}\sum_{i=1}^m(h_\theta{}(x^i)-y^i)^2+\frac{\lambda}{2m}\sum_{j=1}^n\theta_j^2\]</span> 这时最小二乘的话就很简单了，因为后面那一项相当于是加了一个对角矩阵。而对于梯度下 降，<span class="math">\(\partial{J}/\partial{\theta_0}\)</span>需要与其它的偏导分别对待，如下: <span class="math">\[\begin{cases}
    \frac{\partial J(\theta)}{\partial{}\theta_0}=\frac{1}{m}\sum_{i=1}^m(\theta^Tx^i-y^i)x_0^i\\ 
    \frac{\partial J(\theta)}{\partial{}\theta_j}=\frac{1}{m}(\sum_{i=1}^m(\theta^Tx^i-y^i)x_j^i+ \lambda\theta_j)\\ 
\end{cases}\]</span> 其中的<span class="math">\(\lambda\)</span>用于调参，当它接近0的时候，正则项就没有什么意义了，而如果它非常大 ，那整个代价函数基本就由这个正则项控制，从而导致<span class="math">\(\theta\)</span>基本为0，显然这样也不是 一个合理的结果，所以选择一个合理的参数也是非常的重要。</p>
<p>对于逻辑回归问题，使用梯度下降的过程中，也是偏导重新调整一下，这里不再赘述。</p>
<hr />
<h3 id="第四周-神经网络之模型表示">第四周 神经网络之模型表示</h3>
<p>神经网络在机器学习的历史中是非常早就提出来的，它通过模拟人的大脑对一个问题的思考 而建立起来一个网络结构。过去十几年，神经网络一直被统计学派所压制，但近年来随着深 度学习的热潮，NN再一次得到兴起。</p>
<h4 id="模型表示">模型表示</h4>
<p>我们知道，在我们的神经结构中，每一个神经元可以看作是一个独立的计算单元，它包含输 入和输出，通过神经将不同神经元连接起来，通过突触实现信号的传递，前一组神经元的输 出可以作为下一组神经元的输入，从而可以模拟出复杂的计算。因此，在神经网络中，也是 通过模拟多层神经元来达到计算的目的，同时使用最简单的<a href="http://en.wikipedia.org/wiki/Sigmoid_function"><code>sigmoid</code>函数</a>作为基本的 计算函数。（注意，多层神经结构中每一层不是仅仅包含一个神经元，视问题的不同，可以 包含多个神经元，每个神经元的输出构成新的特征中一个元素。）</p>
<p>一个简单的神经元如下图</p>
<p><img align="middle" src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/neuron-single.jpg" alt="neuron-single" width="400" /></p>
<p>由于神经网络本身具有多层结构，因此可以将多个神经元组合成如下形式，使得整个网络包 含输入层，训练层和输出层。</p>
<p><img align="middle" src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/neuron-multi.jpg" alt="neuron-multi" width="400" /></p>
<p>为了叙述的方便，将第<span class="math">\(l\)</span>层的输入记为<span class="math">\(a^l\)</span>（其中<span class="math">\(a_0^l\)</span>为1，其余项即前一层的输出， 因此当<span class="math">\(l=1\)</span>即输入层的时候，<span class="math">\(a^1(2:end)\)</span>即输入元素<span class="math">\(x\)</span>，<span class="math">\(i\)</span>表示第i个神经元。由于后 一层的输入是前一层的输出，即<span class="math">\(a^l\)</span>由<span class="math">\(a^{l-1}\)</span>计算得到，因此： <span class="math">\[a^l=g(\Theta^l*a^{l-1})\]</span> ，其中<span class="math">\(\Theta^l\)</span>表示计算第<span class="math">\(l\)</span>层对应的系数，<span class="math">\(g(z)\)</span>为<code>sigmoid</code>函数。如果第 <span class="math">\(l\)</span>层神经元包含<span class="math">\(s_l\)</span>个元素，而<span class="math">\(l-1\)</span>层包含<span class="math">\(s_{l-1}\)</span>个元素，则<span class="math">\(\Theta^l\)</span>为一个 <span class="math">\(s_l\times(s_{l-1}+1)\)</span>的矩阵，加1是对应于前面<span class="math">\(a_0^l\)</span>这个bias项。</p>
<p>令<span class="math">\(z^2=\Theta^1*x\)</span>，考虑到<span class="math">\(a^1=[1\quad{}x&#39;]&#39;\)</span>，我们可以替换为<span class="math">\(z^2=\Theta^1*a^1\)</span>，于是 <span class="math">\(a^2=g(z^2)\)</span>。推广即可简化写为：</p>
<p><img align="middle" src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/ml_forward_propagation.jpg" alt="forward-propogation" width="200"/></p>
<h4 id="简单例子">简单例子</h4>
<p>神经网络可以模拟复杂的函数，其原因在于每一层都相当于是在一个新的特征上进行提取， 从而得到一个更加准确的特征，但采用之前的回归方法，我们只能利用给定的特征进行组合 得到新的结果；但通过多层神经网络，我们可以学习到一些未知的但有非常强区分度的特征 ，从而达到最后的分类/拟合目的。</p>
<p>举个例子，我们想要用神经网络近似逻辑函数“与”，则只需要利用一层神经网络，其中的 系数可以为<span class="math">\(Y=g(-30+20*x_1+20x_2)\)</span>，这样只有当<span class="math">\(x_1=1\)</span>，<span class="math">\(x_2=1\)</span>才会输出结果1，否则 为0。如果我们要近似逻辑函数<code>XOR</code>，则需要利用多层神经网络先实现出<code>OR</code>，然后再实现 <code>XOR</code>。</p>
<hr />
<h3 id="第五周-神经网络之学习算法">第五周 神经网络之学习算法</h3>
<p>神经网络的损失函数可以看作是之前的逻辑回归损失函数的一个推广，表示为： <span class="math">\[\begin{align}
    J(\theta) &amp; = -\frac{1}{m}[\sum_{i=1}^m\sum_{k=1}^K y_k^i \log(h_\Theta(X^i))_k + (1-y_k^i) \log(1-h_\Theta(X^i))_k] \\
    &amp; =  \frac{\lambda}{2m}\sum_{l=1}^{L-1}\sum_{i=1}^{s_l}\sum_{j=1}^{s_{l+1}}(\Theta_{ji}^l)^2
\end{align}\]</span> 其中<span class="math">\(K\)</span>表示最终输出层中神经单元的个数，也即输出结果的维度。<span class="math">\(h_\Theta(x)\)</span>即复杂的 神经网络结构，<span class="math">\(\Theta\)</span>为所有网络层中的参数，<span class="math">\(m\)</span>为训练样本的个数。</p>
<p>那么如何对它进行优化估计出参数<span class="math">\(\Theta\)</span>呢？</p>
<h4 id="反向传播算法">反向传播算法</h4>
<p>为了利用梯度下降的方法，我们每次给定一个<span class="math">\(\Theta\)</span>的初始值后，需要计算出 <span class="math">\(J(\Theta)\)</span>和<span class="math">\(\frac{\partial{}J(\Theta)}{\partial{}\Theta_{ij}^l}\)</span>。但是注意到 <span class="math">\(h_\Theta(x)\)</span>实际上是不能显式地表达成一个解析函数的，所以对各参数梯度的计算并不 如之前那样直观。事实上，反向传播算法是可以计算的。先定义每一个神经元的误差为 <span class="math">\(\delta_i^{(l)}\)</span>，表示第<span class="math">\(l\)</span>层第<span class="math">\(i\)</span>个神经元的误差，显然隐式层的神经元的误差是比较 难计算的，但我们可以通过反向计算从后向前先计算最后输出层的误差。即 <span class="math">\[\delta_i^{(L)}=a_i^{(L)}-y_i\]</span> 向量化即 <span class="math">\(\delta^{(L)}=a^{(L)}-y\)</span> 则 <span class="math">\[\delta^{(L-1)}=(\Theta^{(L-1)})^T\delta^{(L)}~.*~g&#39;(z^{(L-1)})\]</span> 注意这里<code>.*</code>即matlab中每个对应元素分别相乘，以此类推，直到第二层（第一层为输入层 ，没有误差的概念）。</p>
<p>反向传播算法如下图：</p>
<p><img src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/backpropogation.jpg" alt="back-propogation" width="400" /></p>
<p><strong>这里的推导过程比较复杂，还不太懂，有待补充。</strong></p>
<hr />
<h3 id="第六周-机器学习应用与设计">第六周 机器学习应用与设计</h3>
<p>当把前面学到的一些机器学习方法应用到现实的例子中时，经常会碰到学出来的结果不如意 ，这个时候我们就需要考虑多方面的原因了。使用更多训练数据，尝试更少或额外的特征， 增加多项式特征，增大或减小正则系数。</p>
<h4 id="选择正则系数">选择正则系数</h4>
<p>正则系数太小会造成过拟合，系数太大则会欠拟合。可以控制<span class="math">\(\lambda\)</span>生成一系列的 <span class="math">\(J(\theta)\)</span>，然后利用CV数据并选择误差最小（这时的误差可以不加正则控制项）对应的 系数，将这个系数结果应用到测试数据中。</p>
<h4 id="学习曲线">学习曲线</h4>
<p>将误差结果与训练集大小关系以图表的方式画出来，可以想象得出来，如果训练集很小，显 然得到的误差结果是非常小的，但随着训练集的增大，误差的结果是会增大的并最终稳定在 一个水平，因为这个时候拟合的系数需要在所有的结果中作出一权衡。那么交叉验证的数据 集上，学习曲线是会如何变化的呢？显然训练样本数过少是不足以估计准确的系数的，所以 交叉验证的学习曲线是一个逐步减小的趋势，并最终与训练集曲线相接近。</p>
<h4 id="biasvariance">Bias/Variance</h4>
<p>我们知道，一个模型越复杂，它Bias越小，但variance越大。而模型越简单，则越容易出现 bias偏大的情况。</p>
<p><img src="https://dl.dropboxusercontent.com/u/47886630/stackedit/coursera-ml004/ml_bias_variance.jpg" alt="bias-variance" width="400" /></p>
<p>可以说，bias意味着underfitting，variance意味着overfitting。</p>
<p>如果一个算法已经有非常大的bias，那么使用更多的训练集并不会有很大的提高； 而如果有非常大的variance，那么使用更大训练集是有效的。</p>
<p>前面提到的一些改进方法如何对应到bias和variance呢？</p>
<p>增加训练集、尝试更少的特征、增大正则系数均为改进高的variance<br />而增加额外的特征或减小正则系数为改进高的bias。</p>
<p>对于神经网络，可以通过先尝试一些比较小的神经网络结构（更少的隐含层和隐含的单位元），不过易欠拟合。</p>
<h4 id="例垃圾邮件分类器">例：垃圾邮件分类器</h4>
<p>将其中的一些单词抽取出来形成一个向量，并用布尔值标记某个单词在邮件中是否存在，然后使用该向量作为输入向量。</p>
<ol style="list-style-type: decimal">
<li>使用一个最简单易实现的方法并实现它，在交叉验证集上进行测试；</li>
<li>使用前面提到的学习曲线决定是否需要增加训练数据、特征等；</li>
<li>误差分析：当算法在交叉验证集上判断错误时，手工地进行分析判断；</li>
</ol>
<p>误差衡量标准：</p>
<ul>
<li>Precision：true positive / no. of predicted positive</li>
<li>Recall：true positive / no. of actual positive</li>
</ul>
<p>这两者是相互制约着的，因此需要进行一个很好的trade off，这里提供了一个计算方式<span class="math">\(2PR/(P+R)\)</span>进行量化。</p>
<h3 id="第七周-支持向量机svm">第七周 支持向量机（SVM）</h3>
<p>一接触SVM很多人的第一反应是：它能够得出一个最优的划分平面将两类元素划分开。那么其细节如何呢？</p>
<p><a href="http://blog.pluskid.org/?page_id=683">参考链接</a></p>
<p><span class="math">\[ \mathtt{min}_\theta\frac{1}{m} \sum_{i=1}^m y^{(i)}\mathtt{cost}_1(\theta^T x^{(i)}) + (1-y^{(i)})\mathtt{cost}_0(\theta^T x^{(i)}) + \frac{\lambda}{2m}\sum_{j=1}^n\theta_j^2 \]</span></p>
<p><span class="math">\[ \mathtt{min}_\theta C\sum_{i=1}^m y^{(i)}\mathtt{cost}_1(\theta^T x^{(i)}) + (1-y^{(i)})\mathtt{cost}_0(\theta^T x^{(i)}) + \frac{1}{2}\sum_{j=1}^n\theta_j^2 \]</span></p>
<p>前面提到的都是线性的情况，如果是线性不可分的元素呢？这就涉及到核函数的问题了。从前几周的内容可以看到，也可以使用高阶的多项式特征，</p>
<p>Guassian Kernal可以定义出样本与landmark的相似性： <span class="math">\[f_l = G(x, l)=\exp (-\frac{\|x-l\|^2}{2\sigma^2})\]</span></p>
<p>新的拟合函数可以写成 <span class="math">\[h(X) = \Theta^TG(X_i, l_i)\]</span></p>
<p>可以看作是径向基函数的插值？</p>
<p><span class="math">\(C=\frac{1}{\lambda}\)</span>越大，则bias越大而variance越小；<br /><span class="math">\(\sigma\)</span>越大，则特征过渡会越平滑，意味着高bias，低variance。</p>
<h4 id="svm使用">SVM使用</h4>
<p>使用<code>liblinear</code>, <code>libsvm</code>等库求解<span class="math">\(\theta\)</span>，但是需要指定参数<span class="math">\(C\)</span>和Kernal，如果不指 定Kernal，即意味着线性核函数（如果<span class="math">\(\theta^Tx \leq 0\)</span>则预测<span class="math">\(y=1\)</span>），另一种方式是 使用高斯核定义如上式（非线性情况）。</p>
<p>使用<code>Mercer</code>定理衡量Kernal的好坏。</p>
<p>使用SVM处理多分类问题：SVM包提供了多分类函数，也可以使用one vs. all这种方式进行处理。</p>
<p>SVM相对于逻辑回归问题，更适合处理训练样本不是很多的情况。</p>
<h3 id="第八周-聚类与降维pca">第八周 聚类与降维PCA</h3>
<h4 id="聚类clustering">聚类（clustering）</h4>
<p>是一种无监督的方法。</p>
<p><strong>K-Means方法</strong>：先随机选择K个中心点，记为 <span class="math">\(\mu_{1\cdots{}K}\)</span>，每次都计算每个点 到K个中心中最近点的下标<span class="math">\(c^{(i)}\)</span>，然后更新K个中心点。</p>
<p>对于不可分数据：正则的方法去控制。</p>
<p>聚类问题的优化代价函数：</p>
<p><span class="math">\[J(c^{(1)}, \cdots{}, c^{(m)}, \mu_1, \cdots{}, \mu_K) = \frac{1}{m}\sum_{i=1}^m\|x^{(i)}-\mu_{c^{(i)}}|\|^2\]</span></p>
<p>K-Means算法通过先固定中心<span class="math">\(\mu\)</span>求解<span class="math">\(c\)</span>，然后再固定<span class="math">\(c\)</span>重新求解<span class="math">\(\mu\)</span>。</p>
<p><strong>随机初始化</strong>：在K-Means算法初始化阶段，我们使用随机初始化K个中心点。由于方法是 一个非凸的问题，非常容易落入局部极小值。因此，最好尝试对K-Means算法随机初始化并 执行多次，然后取代价最小的那个结果。</p>
<p>另外，选择合适的K也不是一件容易的事情。可以通过绘制K与代价对应的曲线，然后选择合 适的K。</p>
<h4 id="pca">PCA</h4>
<p>使用PCA我们可以将高维信息投影到低维空间，达到降维和压缩数据的目的。从数学角度上 来看，相当于是拟合一个低维的平面使得和数据尽可能地靠近。与线性回归不一样的地方在 于误差的度量，PCA的每个点误差是点到平面的距离平方，而线性回归则是每个点沿坐标轴 到平面的一条线段的距离。一般我们可以使用SVD算法计算一组数据的PCA。</p>
<p>PCA算法流程：</p>
<ol style="list-style-type: decimal">
<li>数据的缩放（Scaling）和均值正则化（Mean Normalization）</li>
<li>计算协方差矩阵<span class="math">\(\Sigma = \frac{1}{m}\sum_{i=1}^m *((x^i)(x^i)^T)\)</span>，计算协方差 矩阵的特征值与特征向量。<code>[U S V] = svd(Sigma)</code> 其中，U矩阵每一列为特征向量，而S为对角矩阵，每个对角元素都是特征值。记第一步之后 的数据为<span class="math">\(X\)</span>，则<span class="math">\(\Sigma=\frac{1}{m}*X^T*X\)</span>，而使用SVD得到特征向量U后，我们可以截 取前面K个向量作为主成分，即<code>U=U(:, 1:K)</code>，于是新的数据可以用<code>z=U'*x</code>生成。</li>
</ol>
<p>此外，我们注意到前面K个向量的K这个数字我们是不确定的，一方面希望能够用尽量少的K 去逼近数据，另一方面又希望它保持原始数据尽可能地多。特征值其实给我们提供了一个很 好的权衡，按特征值大小对特征向量进行排序，特征值越大表示它保留原始数据越多，即越 大的特征值对应的特征向量是越重要的成分。通过计算每个特征向量保留的比例如下， <span class="math">\[1-\frac{\sum_{i=1}^k S_{ii}}{\sum_{i=1}^n S_{ii}}\]</span> 我们可以设定阈值选取合适的K，使得 <span class="math">\[1-\frac{\sum_{i=1}^K S_{ii}}{\sum_{i=1}^n S_{ii}} \geq \mathtt{T}\]</span>。</p>
<p><strong>注意</strong>：在设计ML系统的时候，先使用原始数据进行训练，如果效果不行才先用PCA降维再训练。</p>
<p><strong>NOTES</strong> PCA的推导式如下：<br />注意到我们需要找到一个主成分使得 <span class="math">\[\frac{1}{m}\sum\limits_{i=1}^m|\mathbf{z}^{(i)}|^2=\frac{1}{m}\sum\limits_{i=1}^m\mathbf{u}^T\mathbf{x} ^{(i)} \mathbf{x}^{(i)}{}^T\mathbf{u}\]</span> 定义<span class="math">\(\frac{1}{m}\sum\limits_{i=1}^m\mathbf{x}^{(i)}\mathbf{x}^{(i)}{}^T\)</span>于是，上式可以写成 <span class="math">\[u^T A u\]</span> 同时，<span class="math">\(u\)</span>应该是一个正交矩阵，即满足<span class="math">\(u^T u=I\)</span>，这样最优化问题即： <span class="math">\[\mathtt{arg max}~~u^T A u\quad\mathtt{s.t.}~~u^T u=I\]</span> 使用拉格朗日乘子法，令偏导为0，即得到<span class="math">\(Au=\lambda u\)</span> 这个优化问题的最优解仅当<span class="math">\(u\)</span>为<span class="math">\(A\)</span>的特征向量。</p>
<h3 id="第九周">第九周</h3>
<h4 id="异常检测">异常检测</h4>
<p>通过正常的训练数据对输入数据进行建模，如果某一测试数据使用模型计算后低于一定的阈 值，则为异常数据。具体使用什么模型进行建模呢？</p>
<p><strong>高斯分布</strong>：<span class="math">\[p(x; \mu, \sigma^2) = \mathcal{N}(\mu, \sigma) = \frac{1}{\sqrt{2\pi}\sigma}\exp(-\frac{(x-\mu)^2}{2\sigma^2})\]</span> 根据给定的一系列数据， <span class="math">\(\mu=\frac{1}{m}\sum_{i=1}^m x^{(i)}\)</span>， <span class="math">\(\sigma^2=\frac{1}{m}\sum_{i=1}^m(x^{(i)}-\mu)^2\)</span> ，则测试数据<span class="math">\(\mathbf{x}\in\mathbb{R}^n\)</span>对应的模型为： <span class="math">\[p(\mathbf{x})=\Pi_{j=1}^n p(x_j;\mu_j,\sigma^2_j)\]</span></p>
<p><em>第六周</em></p>
<p>使用监督式学习方法和异常检测的方法有何使用上的区别？异常检测的方法可以适用于两类 别中一个类别数量特别多另一个特别少的情况。</p>
<p>如果不符合高斯分布的数据呢？使用<span class="math">\(\log\)</span>或<span class="math">\(x^{\frac{1}{3}}\)</span>对数据进行变换。</p>
<p><strong>高维高斯分布</strong>：</p>
<p><span class="math">\[p(x; \mu, \Sigma) = \frac{1}{(2\pi)^{n/2}\sqrt{|\Sigma|}}\exp(-1/2(x-\mu)^T\Sigma^{-1}(x-\mu))\]</span></p>
</body>
</html>
